#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#include <sys/stat.h>

static volatile sig_atomic_t stop = 0;
static void on_int(int sig) { (void)sig; stop = 1; }
static void on_term(int sig) { (void)sig; stop = 1; }

int main(void) {
    pid_t pid = fork();
    if (pid < 0) return 1;
    if (pid > 0) _exit(0); // parent exits


    // 记录原始工作目录，供守护化后使用绝对路径写日志
    char project_root[1024];
    if (getcwd(project_root, sizeof(project_root)) == NULL) _exit(1);

    umask(022);  //守护进程通常由不同管理器以非交互方式启动，子进程umask继承自父进程，不保证是 022，所以需要显式设置，不能依赖环境默认
    chdir("/");

    int null = open("/dev/null", O_RDWR);
    if (null >= 0) {
        dup2(null, STDIN_FILENO);
        dup2(null, STDOUT_FILENO);
        dup2(null, STDERR_FILENO);
        if (null > 2) close(null);
    }

    struct sigaction sa = {0};
    sa.sa_handler = on_int; sigemptyset(&sa.sa_mask);
    sigaction(SIGINT, &sa, NULL);
    sa.sa_handler = on_term; sigemptyset(&sa.sa_mask);
    sigaction(SIGTERM, &sa, NULL);

    while (!stop) {
        char log_path[1200];
        snprintf(log_path, sizeof(log_path), "%s/logs/daemon_heartbeat.log", project_root);
        int fd = open(log_path, O_WRONLY | O_CREAT | O_APPEND, 0644);
        if (fd >= 0) {
            char buf[128];
            time_t now = time(NULL);
            char ts[32];
            strftime(ts, sizeof(ts), "%F %T", localtime(&now));
            int len = snprintf(buf, sizeof(buf), "[%s] heartbeat pid=%d\n", ts, getpid());
            write(fd, buf, len);
        }
        sleep(1);
    }

    return 0;
}
